package com.jasonchoi.gatewaydynamicroute.routes.dao;

import com.alibaba.fastjson.JSONObject;
import com.jasonchoi.gatewaydynamicroute.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: JasonChoi
 * @Date: 2019/12/19 10:59
 */
@Repository
public class RedisRouteDefinitionRepository implements RouteDefinitionLocator {
    /**
     * 动态路由存储的redis key
     */
    private final static String KEY = "gateway_dynamic_route";

    @Autowired
    private RedisUtil redisUtils;

    /**
     * 获取路由信息(初始化)
     * @return
     */
    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        List<RouteDefinition> gatewayRouteEntityList = new ArrayList<>();
        redisUtils.hValues(KEY).stream().forEach(route -> {
            RouteDefinition result = JSONObject.parseObject(route.toString(), RouteDefinition.class);
            gatewayRouteEntityList.add(result);
        });
        return Flux.fromIterable(gatewayRouteEntityList);
    }

    /**
     * 新增
     * @param route
     * @return
     */
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return route.flatMap(routeDefinition -> {
            redisUtils.hPut(KEY, routeDefinition.getId(), JSONObject.toJSONString(routeDefinition));
            return Mono.empty();
        });
    }

    /**
     * 删除
     * @param routeId
     * @return
     */
    public Mono<Void> delete(Mono<String> routeId) {
        return routeId.flatMap(id -> {
            if (redisUtils.hExists(KEY, id)) {
                redisUtils.hDelete(KEY, id);
                return Mono.empty();
            }
            return Mono.defer(() -> Mono.error(new NotFoundException("route definition is not found, routeId:" +  routeId)));
        });
    }
}
